/*
 * This file Copyright (c) 2015. Walle.
 * (http://www.wallellen.com). All rights reserved.
 *
 *
 * This file is dual-licensed under both the
 * Walle Agreement (WA) and the GNU General Public License.
 * You may elect to use one or the other of these licenses.
 *
 * This file is distributed in the hope that it will be
 * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
 * Redistribution, except as permitted by whichever of the GPL
 * or WA you select, is prohibited.
 *
 * 1. For the GPL license (GPL), you can redistribute and/or
 * modify this file under the terms of the GNU General
 * Public License, Version 3, as published by the Free Software
 * Foundation.  You should have received a copy of the GNU
 * General Public License, Version 3 along with this program;
 * if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 2. For the Walle Agreement (WA), this file
 * and the accompanying materials are made available under the
 * terms of the WA which accompanies this distribution, and
 * is available at http://www.wallellen.com/agreement.html
 *
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 */

package com.wallellen.quartz.server.impl;

import com.wallellen.core.auth.domain.LoginUser;
import com.wallellen.core.sql.query.DataQuery;
import com.wallellen.core.time.TimeTool;
import com.wallellen.quartz.dao.QzSchedulerDaoInter;
import com.wallellen.quartz.dao.QzTaskDaoInter;
import com.wallellen.quartz.dao.QzTriggerDaoInter;
import com.wallellen.quartz.domain.QzScheduler;
import com.wallellen.quartz.domain.QzTask;
import com.wallellen.quartz.domain.QzTrigger;
import com.wallellen.quartz.server.QzSchedulerManagerInter;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.text.ParseException;

/**
 * 计划任务管理
 */
@Service
public class QzSchedulerManagerImpl implements QzSchedulerManagerInter {
    @Resource
    private QzSchedulerDaoInter farmQzSchedulerDao;
    @Resource
    private QzTaskDaoInter farmQzTaskDao;
    @Resource
    private QzTriggerDaoInter farmQzTriggerDao;

    private static final Logger log = LoggerFactory
            .getLogger(QzSchedulerManagerImpl.class);

    private static Scheduler scheduler = null;

    @Override
    @Transactional
    public void start() throws SchedulerException, ParseException,
            ClassNotFoundException {
        if (scheduler == null) {
            scheduler = StdSchedulerFactory.getDefaultScheduler();
        }
        scheduler.start();
        for (QzScheduler node : farmQzSchedulerDao.getAutoSchedulers()) {
            QzTask task = getTaskEntity(node.getTaskid());
            QzTrigger trigger = getTriggerEntity(node.getTriggerid());
            JobDetail job = new QuartzImpl().getJobDetail(node, task);
            Trigger qtrigger = new QuartzImpl().getTrigger(node, trigger);
            scheduler.scheduleJob(job, qtrigger);
        }
    }

    @Override
    @Transactional
    public boolean isRunningFindScheduler(String SchedulerId)
            throws SchedulerException {
        QzScheduler node = getSchedulerEntity(SchedulerId);
        QzTask task = getTaskEntity(node.getTaskid());
        if (scheduler.getJobDetail(new QuartzImpl().getJobKey(node, task)) == null) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    @Transactional
    public void startTask(String SchedulerId) throws ClassNotFoundException,
            ParseException, SchedulerException {
        QzScheduler node = getSchedulerEntity(SchedulerId);
        QzTask task = getTaskEntity(node.getTaskid());
        QzTrigger trigger = getTriggerEntity(node.getTriggerid());
        JobDetail job = new QuartzImpl().getJobDetail(node, task);
        Trigger qtrigger = new QuartzImpl().getTrigger(node, trigger);
        scheduler.scheduleJob(job, qtrigger);
    }

    @Override
    @Transactional
    public void stopTask(String SchedulerId) throws SchedulerException {
        QzScheduler node = getSchedulerEntity(SchedulerId);
        QzTask task = getTaskEntity(node.getTaskid());
        scheduler.deleteJob(new QuartzImpl().getJobKey(node, task));
    }

    @Override
    @Transactional
    public QzScheduler insertSchedulerEntity(QzScheduler entity,
                                             LoginUser user) {
        entity.setCuser(user.getId());
        entity.setCtime(TimeTool.getTimeDate14());
        entity.setCusername(user.getName());
        entity.setEuser(user.getId());
        entity.setEusername(user.getName());
        entity.setEtime(TimeTool.getTimeDate14());
        entity.setPstate("1");
        entity = farmQzSchedulerDao.insertEntity(entity);
        if (entity.getAutois().equals("1")) {
            try {
                startTask(entity.getId());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return farmQzSchedulerDao.insertEntity(entity);
    }

    @Override
    @Transactional
    public QzScheduler editSchedulerEntity(QzScheduler entity,
                                           LoginUser user) {
        QzScheduler entity2 = farmQzSchedulerDao.getEntity(entity.getId());
        entity2.setEuser(user.getId());
        entity2.setEusername(user.getName());
        entity2.setEtime(TimeTool.getTimeDate14());
        entity2.setAutois(entity.getAutois());
        entity2.setTaskid(entity.getTaskid());
        entity2.setTriggerid(entity.getTriggerid());
        farmQzSchedulerDao.editEntity(entity2);
        return entity2;
    }

    @Override
    @Transactional
    public void deleteSchedulerEntity(String entity, LoginUser user) {
        try {
            stopTask(entity);
        } catch (SchedulerException e) {
            log.error(e.getMessage(), e);
        }
        farmQzSchedulerDao.deleteEntity(farmQzSchedulerDao.getEntity(entity));
    }

    @Override
    @Transactional
    public QzScheduler getSchedulerEntity(String id) {
        if (id == null) {
            return null;
        }
        return farmQzSchedulerDao.getEntity(id);
    }

    @Override
    @Transactional
    public DataQuery createSchedulerSimpleQuery(DataQuery query) {
        DataQuery dbQuery = DataQuery
                .init(query,
                        "FARM_QZ_SCHEDULER A LEFT JOIN FARM_QZ_TASK B ON A.TASKID=B.ID LEFT JOIN FARM_QZ_TRIGGER C ON A.TRIGGERID=C.ID",
                        "A.ID AS ID,A.AUTOIS AS AUTOIS,A.AUTOIS AS AUTOISTYPE,B.NAME AS TASKNAME,C.NAME AS CTRIGGERNAME");
        return dbQuery;
    }

    @Override
    @Transactional
    public QzTask insertTaskEntity(QzTask entity, LoginUser user) {
        entity.setCuser(user.getId());
        entity.setCtime(TimeTool.getTimeDate14());
        entity.setCusername(user.getName());
        entity.setEuser(user.getId());
        entity.setEusername(user.getName());
        entity.setEtime(TimeTool.getTimeDate14());
        entity.setPstate("1");
        entity.setJobkey("NONE");
        try {
            for (@SuppressWarnings("rawtypes")
            Class cla : Class.forName(entity.getJobclass().trim())
                    .getInterfaces()) {
                if (cla.equals(Job.class)) {
                    return farmQzTaskDao.insertEntity(entity);
                }
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("类转化异常");
        }
        throw new RuntimeException("类为实现Job接口");
    }

    @Override
    @Transactional
    public QzTask editTaskEntity(QzTask entity, LoginUser user) {
        QzTask entity2 = farmQzTaskDao.getEntity(entity.getId());
        entity2.setEuser(user.getId());
        entity2.setEusername(user.getName());
        entity2.setEtime(TimeTool.getTimeDate14());
        entity2.setJobclass(entity.getJobclass());
        entity2.setName(entity.getName());
        entity2.setJobkey(entity.getJobkey());
        entity2.setJobparas(entity.getJobparas());
        entity2.setJobkey("NONE");
        entity2.setPcontent(entity.getPcontent());
        try {
            for (@SuppressWarnings("rawtypes")
            Class cla : Class.forName(entity2.getJobclass().trim())
                    .getInterfaces()) {
                if (cla.equals(Job.class)) {
                    farmQzTaskDao.editEntity(entity2);
                    return entity2;
                }
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("类转化异常");
        }
        throw new RuntimeException("类为实现Job接口");

    }

    @Override
    @Transactional
    public void deleteTaskEntity(String entity, LoginUser user) {
        farmQzTaskDao.deleteEntity(farmQzTaskDao.getEntity(entity));
    }

    @Override
    @Transactional
    public QzTask getTaskEntity(String id) {
        if (id == null) {
            return null;
        }
        return farmQzTaskDao.getEntity(id);
    }

    @Override
    public DataQuery createTaskSimpleQuery(DataQuery query) {
        DataQuery dbQuery = DataQuery.init(query, "farm_qz_task",
                "id,JOBCLASS,NAME,JOBKEY");
        return dbQuery;
    }

    @Override
    @Transactional
    public QzTrigger insertTriggerEntity(QzTrigger entity,
                                         LoginUser user) {
        entity.setCuser(user.getId());
        entity.setCtime(TimeTool.getTimeDate14());
        entity.setCusername(user.getName());
        entity.setEuser(user.getId());
        entity.setEusername(user.getName());
        entity.setEtime(TimeTool.getTimeDate14());
        entity.setPstate("1");
        return farmQzTriggerDao.insertEntity(entity);
    }

    @Override
    @Transactional
    public QzTrigger editTriggerEntity(QzTrigger entity, LoginUser user) {
        QzTrigger entity2 = farmQzTriggerDao.getEntity(entity.getId());
        // entity2.setEuser(user.getId());
        // entity2.setEusername(user.getName());
        // entity2.setEtime(TimeTool.getTimeDate14());
        entity2.setPcontent(entity.getPcontent());
        entity2.setDescript(entity.getDescript());
        entity2.setName(entity.getName());
        farmQzTriggerDao.editEntity(entity2);
        return entity2;
    }

    @Override
    @Transactional
    public void deleteTriggerEntity(String entity, LoginUser user) {
        farmQzTriggerDao.deleteEntity(farmQzTriggerDao.getEntity(entity));
    }

    @Override
    @Transactional
    public QzTrigger getTriggerEntity(String id) {
        if (id == null) {
            return null;
        }
        return farmQzTriggerDao.getEntity(id);
    }

    @Override
    @Transactional
    public DataQuery createTriggerSimpleQuery(DataQuery query) {
        DataQuery dbQuery = DataQuery.init(query, "farm_qz_trigger",
                "id,PCONTENT,DESCRIPT,NAME");
        return dbQuery;
    }

    @Override
    @Transactional
    public QzTask getTaskBySchedulerId(String schedulerId) {
        return farmQzTaskDao.getEntity(farmQzSchedulerDao
                .getEntity(schedulerId).getTaskid());
    }

}
